package jp.wug.core;

import org.w3c.dom.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Preprocessor {
    public void preprocess(Document document) {
        preprocess0(document);
        document.normalizeDocument();
    }

    private void preprocess0(Node node) {
        Pattern exactPattern = Pattern.compile("^\\$\\{(\\w+(\\.\\w+)*)\\}$");
        Pattern pattern = Pattern.compile("\\$\\{(\\w+(\\.\\w+)*)\\}");
        NodeList childNodes = node.getChildNodes();
        List<Node> children = new ArrayList<Node>();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node child = childNodes.item(i);
            children.add(child);
        }

        for (Node child : children) {
            switch (child.getNodeType()) {
                case Node.ELEMENT_NODE:
                    Element element = (Element) child;
                    List<Attr> attrs = new ArrayList<Attr>();
                    NamedNodeMap namedNodeMap = element.getAttributes();
                    for (int i = 0; i < namedNodeMap.getLength(); i++) {
                        attrs.add((Attr) namedNodeMap.item(i));
                    }
                    for (Attr attr : attrs) {
                        Matcher matcher = exactPattern.matcher(attr.getNodeValue());
                        if (matcher.find()) {
                            String value = attr.getNodeName() + ":" + matcher.group(1);
                            if (attr.getOwnerElement().hasAttributeNS(TemplateEngine.NS, "attr")) {
                                value = attr.getOwnerElement().getAttributeNS(TemplateEngine.NS, "attr") + "," + value;
                            }
                            attr.getOwnerElement().setAttributeNS(TemplateEngine.NS, "attr", value);
                            attr.getOwnerElement().removeAttributeNode(attr);
                        }
                    }
                    preprocess0(child);
                    break;
                case Node.TEXT_NODE:
                    Text text = (Text) child;
                    Map<Text, String> labelNodes = new HashMap<Text, String>();
                    String nodeValue = text.getNodeValue();
                    Matcher matcher = pattern.matcher(nodeValue);
                    int offset = 0;
                    while (matcher.find()) {
                        text = text.splitText(offset + matcher.start());
                        labelNodes.put(text, matcher.group(1));
                        text = text.splitText(matcher.end() - matcher.start());
                        offset += matcher.end();
                    }
                    for (Map.Entry<Text, String> entry : labelNodes.entrySet()) {
                        Element newElement = child.getOwnerDocument().createElementNS(TemplateEngine.NS, "e");
                        newElement.setAttributeNS(TemplateEngine.NS, "label", entry.getValue());
                        Text labelNode = entry.getKey();
                        labelNode.getParentNode().insertBefore(newElement, labelNode);
                        labelNode.getParentNode().removeChild(labelNode);
                    }

                    break;
                default:
            }
        }
    }
}
